﻿#include "utils.h"

namespace util {
std::string make_uuid() {
    std::string                    uuid;
    boost::uuids::random_generator rgen;
    boost::uuids::uuid             u = rgen();
    std::stringstream              ss;
    ss << u;
    ss >> uuid;

    return uuid;
}

std::size_t cal_hash(const std::string& src) {
    std::size_t seed = 0;
    for (auto it = src.begin(); it != src.end(); ++it)
        seed ^= size_t(*it) + 0x9e3779b9 + (seed << 6) + (seed >> 2);

    return seed;
}

std::size_t make_uuid_hash() {
    std::string uuid = make_uuid();
    return cal_hash(uuid);
}

std::string cal_sha1(const std::string& src) {
    char                       hash[20];
    boost::uuids::detail::sha1 boost_sha1;
    boost_sha1.process_bytes(src.c_str(), src.size());
    boost::uuids::detail::sha1::digest_type digest;
    boost_sha1.get_digest(digest);
    for (int i = 0; i < 5; ++i) {
        const char* tmp = reinterpret_cast<char*>(digest);
        hash[i * 4]     = tmp[i * 4 + 3];
        hash[i * 4 + 1] = tmp[i * 4 + 2];
        hash[i * 4 + 2] = tmp[i * 4 + 1];
        hash[i * 4 + 3] = tmp[i * 4];
    }

    std::string        str_sha1;
    std::ostringstream buf;
    for (int i = 0; i < 20; ++i) {
        buf << std::setiosflags(std::ios::uppercase) << std::hex << ((hash[i] & 0x0000000F0) >> 4);
        buf << std::setiosflags(std::ios::uppercase) << std::hex << (hash[i] & 0x00000000F);
    }

    str_sha1 = buf.str();
    return str_sha1;
}

std::string cal_md5(const std::string& src) {
    std::string str_md5;

    if (src.empty())
        return "";

    boost::uuids::detail::md5 boost_md5;
    boost_md5.process_bytes(src.c_str(), src.size());
    boost::uuids::detail::md5::digest_type digest;
    boost_md5.get_digest(digest);
    const auto char_digest = reinterpret_cast<const char*>(&digest);
    str_md5.clear();
    boost::algorithm::hex(char_digest,
                          char_digest + sizeof(boost::uuids::detail::md5::digest_type),
                          std::back_inserter(str_md5));

    return str_md5;
}

std::string get_cpuid() {
    std::array<int, 4>
        cpui;   // #include <array>
                //  Calling __cpuid with 0x0 as the function_id argument
                //  gets the number of the highest valid function ID.  什么是function ID？
    __cpuid(cpui.data(), 0x0);               // cpui[0] = "funcition_id的最大值"
    int                             nIds_ = cpui[0];
    std::vector<std::array<int, 4>> data_;   // 保存遍历到的所有cpui的值
    for (int i = 0; i <= nIds_; ++i) {
        __cpuidex(cpui.data(), i, 0);
        data_.push_back(cpui);
    }
    // reinterpret_cast<int*>(vendor) //*reinterpret_cast<int*>(vendor)
    // 索引0 0+4 0+8的值构成了CPU芯片的名称
    char vendor[0x20]                   = {0};
    *reinterpret_cast<int*>(vendor)     = data_[0][1];
    *reinterpret_cast<int*>(vendor + 4) = data_[0][3];
    *reinterpret_cast<int*>(vendor + 8) = data_[0][2];   // vendor="GenuineIntel"
    std::string vendor_                 = vendor;
    bool        isIntel_                = false;
    bool        isAMD                   = false;
    if ("GenuineIntel" == vendor_) {
        isIntel_ = true;   // 厂商为INTEL
    } else if ("AuthenticAMD" == vendor_) {
        isAMD = true;      // 厂商为AMD
    }
    char vendor_serialnumber[0x14] = {0};
    sprintf_s(
        vendor_serialnumber, sizeof(vendor_serialnumber), "%08X%08X", data_[1][3], data_[1][0]);
    // 用“wmic cpu get processorid”获取的结果进行比对，结果应该是一致的。 //vendor_serialnumber =
    //"BFEBFBFF000406E3";
    //  std::cout << "ProcessorId is [ " << vendor_serialnumber << " ]" << std::endl;

    return std::string(vendor_serialnumber);
}

int make_default_color(int index) {
    int color(0);

    if (index == 0)
        color = 0xff;
    else if (index == 1)
        color = 0xff00;
    else if (index == 2)
        color = 0xff0000;
    else if (index == 3)
        color = 0xffff;
    else if (index == 4)
        color = 0xff00ff;
    else if (index == 5)
        color = 0xffff00;
    else if (index == 6)
        color = 0x0a0a4;
    else {
        std::random_device seed;                           // 硬件生成随机数种子
        std::ranlux48      engine(seed());                 // 利用种子生成随机数引擎
        std::uniform_int_distribution<> distrib(0, 255);   // 设置随机数范围，并为均匀分布

        int r, g, b;
        r     = distrib(engine) << 16;
        g     = distrib(engine) << 8;
        b     = distrib(engine);
        color = r + g + b;
    }

    return color;
}
}   // namespace util
